package controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import search.SearchTuple;
import model.Model;
/**
 * this class use as a connection between the view and the model 
 * @author ran & barak
 *
 */
public class CommandsExcuter {
	//all command have a member and he is the one and only instance of this command executer
	private GetInfoExcutor getInfo;
	private GetFoldersExcutor getFolders; 
	private StartExcutor start;
	private StopExcutor stop;
	private AddFolderExcutor addFolder;
	private AddPlugExcutor addPlug;
	private SearchExcutor search;
	private GoToWebExcutor goToWeb;
	private OpenFileExcutor openFile;
	private AdvancedSearchExcutor advancedSearsh;
	private ChangeTagAlgoValidExcutor changeTagAlgoValid;
	//static member for singelton pattern
	private static CommandsExcuter command=new CommandsExcuter();
	/**
	 * @return command member 
	 */
	public static CommandsExcuter getCommand(){
		return command;
	}
	/*
	 * constructor of this class activated only a single time in the program
	 */
	private CommandsExcuter(){
		getInfo= new GetInfoExcutor();
		getFolders=new GetFoldersExcutor();
		start=new StartExcutor();
		stop=new StopExcutor();
		addFolder=new AddFolderExcutor();
		addPlug=new AddPlugExcutor();
		search=new SearchExcutor();
		goToWeb=new GoToWebExcutor();
		openFile = new OpenFileExcutor();
		advancedSearsh = new AdvancedSearchExcutor();
		changeTagAlgoValid = new ChangeTagAlgoValidExcutor();

	}
	

	
	/**
	 * @return ChangeTagAlgoValidExcutor 
	 */
	public ChangeTagAlgoValidExcutor getChangeTagAlgoValid(){
		return changeTagAlgoValid;
	}
	/**
	 * @return AdvancedSearchExcutor 
	 */
	public AdvancedSearchExcutor getAdvancedSearch(){
		return advancedSearsh;
	}
	/**
	 * @return OpenFileExcutor 
	 */
	public OpenFileExcutor getOpenFile(){
		return openFile;
	}
	/**
	 * @return GetInfoExcutor 
	 */
	public GetInfoExcutor getGetInfo() {
		return getInfo;
	}
	/**
	 * @return GetFoldersExcutor 
	 */
	public GetFoldersExcutor getGetFolders() {
		return getFolders;
	}
	/**
	 * @return StartExcutor 
	 */
	public StartExcutor getStart() {
		return start;
	}
	/**
	 * @return StopExcutor 
	 */
	public StopExcutor getStop() {
		return stop;
	}
	/**
	 * @return AddFolderExcutor 
	 */
	public AddFolderExcutor getAddFolder() {
		return addFolder;
	}
	/**
	 * @return AddPlugExcutor 
	 */
	public AddPlugExcutor getAddPlug() {
		return addPlug;
	}
	/**
	 * @return SearchExcutor 
	 */
	public SearchExcutor getSearch() {
		return search;
	}
	/**
	 * @return GoToWebExcutor 
	 */
	public GoToWebExcutor getGoToWeb() {
		return goToWeb;
	}
	
	/**
	 * common interface to all command executors
	 * @author ran & barak
	 *
	 */
	public interface Command {
		/**
		 * the main method of executor class that execute the command 
		 * by activate a certain method in the modal 
		 * all classes that implement this interface must implement this method
		 */
		public void excute() ;

	}
	/**
	 * Inner class that excute the "advanced search" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class AdvancedSearchExcutor implements Command{
		//reference to the model
		Model model;
		ArrayList<String> tags;
		ArrayList<SearchTuple> retVal;
		
		/**
		 * cons` of the executor class
		 */
		private AdvancedSearchExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * set method of the member tags
		 * @param tags new value that need to be assign to the member
		 */
		public void setAdvancedSearch(ArrayList<String> tags){
			this.tags=tags;
		}
		/**
		 * @return the value of member retVal
		 */
		public ArrayList<SearchTuple> getRetVal() {
			return retVal;
		}
		/**
		 * acutely excute the command
		 */
		public void excute() {
			retVal=model.advancedSearch(tags);
			
		}
			
	}
	/**
	 * Inner class that excute the "setting of tags algorithm" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class ChangeTagAlgoValidExcutor implements Command{
		//reference to the model
		Model model;
		ArrayList<String> tagTypes;
		/*
		 * cons` of the executor class
		 */
		private ChangeTagAlgoValidExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			model.changeTagAlgoValid(tagTypes);
		}
		/**
		 * set method of the member tagTypes
		 * @param tagTypes new value that need to be assign to the member
		 */
		public void setPath(ArrayList<String> tagTypes){
			this.tagTypes=tagTypes;
		}
			
	}
	/**
	 * Inner class that excute the "Open file" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class OpenFileExcutor implements Command{
		//reference to the model
		Model model;
		String path;
		/*
		 * cons` of the executor class
		 */
		private OpenFileExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			model.openFile(path);
		}
		/**
		 * set method of the member path
		 * @param path new value that need to be assign to the member
		 */
		public void setPath(String path){
			this.path=path;
		}
			
	}
	/**
	 * Inner class that excute the "get information" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class GetInfoExcutor  implements Command {
		//reference to the model
		Model model;
		ArrayList<ArrayList<String>> retVal;
		/*
		 * cons` of the executor class
		 */
		private GetInfoExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			retVal = model.getInfo();
		}
		
		/**
		 * 
		 * @return the value of member retVal
		 */
		public ArrayList<ArrayList<String>> getRetVal() {
			return retVal;
		}
			

	}
	/**
	 * Inner class that excute the "get folders" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class GetFoldersExcutor  implements Command {
		//reference to the model
		Model model;
		Set<String> returnVal;
		
		/**
		 * cons` of the executor class
		 */
		private GetFoldersExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			returnVal=model.getFolders();
		}
		/**
		 * 
		 * @return the value of member retVal
		 */
		public Set<String> getReturnVal() {
			return returnVal;
			
		}
		

	}

	/**
	 * Inner class that excute the "go to web site" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class GoToWebExcutor  implements Command {
		//reference to the model
		Model model;
		/*
		 * cons` of the executor class
		 */
		private GoToWebExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			model.goToWeb();
			}
	}
	/**
	 * Inner class that excute the "start service" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class StartExcutor  implements Command {
		//reference to the model
		Model model;
		/*
		 * cons` of the executor class
		 */
		private StartExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			model.startListen();
		}
	}
	/**
	 * Inner class that excute the "stop service" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class StopExcutor  implements Command {
		//reference to the model
		Model model;
		/*
		 * cons` of the executor class
		 */
		private StopExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			model.stopListen();
		}

	}
	/**
	 * Inner class that excute the "add folder" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class AddFolderExcutor  implements Command {
		//reference to the model
		private Model model;
		private String path;
		private ArrayList<String> emails;
		private ArrayList<String> selectedFolders;
		private boolean retVal=true;
		/*
		 * cons` of the executor class
		 */
		private AddFolderExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			if(!model.addNewFolder(path,emails,selectedFolders))
				retVal=false;
		}
		/**
		 * set method of the member path
		 * @param path new value that need to be assign to the member
		 */
		public void setPath(String path) {
			this.path=path;
			
		}
		/**
		 * set method of the member emails
		 * @param emails new value that need to be assign to the member
		 */
		public void setEmails(ArrayList<String> emails) {
			this.emails=new ArrayList<String>();
			this.emails=emails;
			
		}
		/**
		 * set method of the member selectedFolders
		 * @param selectedFolders2 new value that need to be assign to the member
		 */
		public void setFolders(ArrayList<String> selectedFolders2) {
			selectedFolders=selectedFolders2;
			
		}
		/** 
		 * @return the value of member retVal
		 */
		public boolean getRetVal(){
			return retVal;
		}

	}
	/**
	 * Inner class that excute the "add plug in" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class AddPlugExcutor  implements Command {
		//reference to the model
		Model model;
		String path;
		private ArrayList<String> retVal;
		/*
		 * cons` of the executor class
		 */
		private AddPlugExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			retVal=model.addPlugIn(path);
		}
		/**
		 * set method of the member path
		 * @param text new value that need to be assign to the member
		 */
		public void setPath(String text) {
			path=text;
			
		}
		/** 
		 * @return the value of member retVal
		 */
		public ArrayList<String> getRetVal() {
			return retVal;
		}

	}
	/**
	 * Inner class that excute the "regular search" command 
	 * from the view to the model
	 * @author ran & barak
	 *
	 */
	public class SearchExcutor  implements Command {
		//reference to the model
		Model model;
		String tag;
		ArrayList<String> tagTypeList;
		ArrayList<SearchTuple> retVal;
		/*
		 * cons` of the executor class
		 */
		private SearchExcutor(){
			this.model=Model.getModel();
			
		}
		/**
		 * acutely excute the command
		 */
		public void excute(){
			retVal=model.searchInDB(tag,tagTypeList);
		}
		/**
		 * set method of the member tag
		 * @param line new value that need to be assign to the member
		 */
		public void setTag(String line) {
			tag=line;
	    }
		/**
		 * set method of the member tagTypeList
		 * @param typeList new value that need to be assign to the member
		 */
		public void setTagType(ArrayList<String> typeList) {
			tagTypeList=typeList;
	    }
		/** 
		 * @return the value of member retVal
		 */
		public ArrayList<SearchTuple> getRetVal(){
			return retVal;
		}

	}

}
